//
//  MKImageViewCell.swift
//  MKPhotoDetailDemo
//
//  Created by 劢克科技 on 2019/3/26.
//  Copyright © 2019 劢克科技. All rights reserved.
//

import UIKit
import SDWebImage

protocol MKImageViewCellDelegate {
    func cellDidTap()
    func shouldScroll(bool: Bool)
    func dismissNow()
    func clearBg()
    func fillBg()
    func btnClick(index: Int)
}

class MKImageViewCell: UICollectionViewCell {
    
    //MARK: - Life Cycle
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        setUI()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func prepareForReuse() {
        currentIndex = 0
        browseImageView.image = nil
        scrollView.zoomScale = 1
        scrollView.maximumZoomScale = 5
        startInteract = false
        shouldStart = false
        browseImageView.sd_cancelCurrentImageLoad()
        textView.removeFromSuperview()
        downloadLayer.removeFromSuperlayer()
        super.prepareForReuse()
    }
    
    //MARK: - Setter
    
    var currentIndex = 0
    var initFrame: CGRect?
    
    var imageData: MKImageData? {
        didSet {
            self.browseImageView.sd_setHighlightedImage(with: imageData?.imageUrl, options: SDWebImageOptions.allowInvalidSSLCertificates, progress: { (size, total, _) in
                let percent = CGFloat(size) / CGFloat(total)
                DispatchQueue.main.sync {
                    if self.downloadLayer.superlayer == nil {
                        self.layer.addSublayer(self.downloadLayer)
                    }
                    self.downloadLayer.strokeEnd = percent < 0.1 ? 0.1 : percent
                }
            }) { (image, _, _, _) in
                self.downloadLayer.removeFromSuperlayer()
                guard let image = image else { return }
                let imageSize = image.size
                var browseW = UIScreen.main.bounds.width
                var browseH = imageSize.height * UIScreen.main.bounds.width / imageSize.width
                var browseX: CGFloat = 0
                var y = (UIScreen.main.bounds.height - browseH) / 2
                y = y < 0 ? 0 : y
                if UIScreen.main.bounds.height < browseH {
                    browseW = UIScreen.main.bounds.width * UIScreen.main.bounds.height / browseH
                    browseH = UIScreen.main.bounds.height
                    browseX = (UIScreen.main.bounds.width - browseW) / 2
                    self.scrollView.maximumZoomScale = UIScreen.main.bounds.width / browseW
                }
                self.browseImageView.image = image
                self.browseImageView.frame = CGRect(x: browseX, y: y, width: browseW, height: browseH)
                self.scrollView.contentSize = CGSize(width: browseW, height: browseH)
                self.initFrame = CGRect(x: browseX, y: y, width: browseW, height: browseH)
                return
            }
        }
    }
    
    fileprivate func setUpText() {
        addSubview(textView)
        textView.leftAnchor.constraint(equalTo: leftAnchor, constant: 0).isActive = true
        textView.rightAnchor.constraint(equalTo: rightAnchor, constant: 0).isActive = true
        if #available(iOS 11.0, *) {
            textView.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
        } else {
            textView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0).isActive = true
        }
        
        textView.addSubview(textTitle)
        textTitle.leftAnchor.constraint(equalTo: textView.leftAnchor, constant: 10).isActive = true
        textTitle.topAnchor.constraint(equalTo: textView.topAnchor, constant: 10).isActive = true
        
        textView.addSubview(button)
        button.rightAnchor.constraint(equalTo: textView.rightAnchor, constant: -10).isActive = true
        button.topAnchor.constraint(equalTo: textView.topAnchor, constant: 5).isActive = true
        
        textView.addSubview(textSort)
        textSort.leftAnchor.constraint(equalTo: textView.leftAnchor, constant: 10).isActive = true
        textSort.topAnchor.constraint(equalTo: textTitle.bottomAnchor, constant: 5).isActive = true

        textView.addSubview(textContent)
        textContent.leftAnchor.constraint(equalTo: textView.leftAnchor, constant: 10).isActive = true
        textContent.topAnchor.constraint(equalTo: textSort.bottomAnchor, constant: 5).isActive = true
        textContent.rightAnchor.constraint(equalTo: textView.rightAnchor, constant: -10).isActive = true

        textView.addSubview(textTime)
        textTime.leftAnchor.constraint(equalTo: textView.leftAnchor, constant: 10).isActive = true
        textTime.topAnchor.constraint(equalTo: textContent.bottomAnchor, constant: 5).isActive = true
        textTime.bottomAnchor.constraint(equalTo: textView.bottomAnchor, constant: -10).isActive = true
    }
    
    var textInfo = false {
        didSet {
            if textInfo {
                textTitle.text = imageData?.username
                textSort.text = imageData?.sortname
                textContent.text = imageData?.content
                textTime.text = imageData?.time
                setUpText()
            }
        }
    }
    
    //MARK: - Getter
    
    var startPoint = CGPoint.zero
    
    var startInteract = false
    
    var shouldStart = false
    
    var isZooming = false
    
    var delegate: MKImageViewCellDelegate?
    
    fileprivate lazy var browseImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFill
        imageView.clipsToBounds = true
        return imageView
    }()
    
    lazy var scrollView: UIScrollView = {
        let scrollView = UIScrollView()
        scrollView.frame = bounds
        scrollView.minimumZoomScale = 1
        scrollView.maximumZoomScale = 5
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture))
        let doubleGesture = UITapGestureRecognizer(target: self, action: #selector(handleDoubleGesture(gesture:)))
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(gesture:)))
        doubleGesture.numberOfTapsRequired = 2
        panGesture.delegate = self
        panGesture.maximumNumberOfTouches = 1
        scrollView.addGestureRecognizer(tapGesture)
        scrollView.addGestureRecognizer(panGesture)
        scrollView.addGestureRecognizer(doubleGesture)
        tapGesture.require(toFail: doubleGesture)
        tapGesture.require(toFail: panGesture)
        scrollView.delegate = self
        scrollView.showsHorizontalScrollIndicator = false
        scrollView.showsVerticalScrollIndicator = false
        return scrollView
    }()
    
    lazy var textView: UIView = {
        let view = UIView()
        view.backgroundColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0.7999284771)
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()
    
    lazy var textTitle: UILabel = {
        let label = UILabel()
        label.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
        label.font = UIFont.systemFont(ofSize: 16)
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    lazy var textSort: UILabel = {
        let label = UILabel()
        label.textColor = #colorLiteral(red: 0.6077751517, green: 0.6078823209, blue: 0.6077683568, alpha: 1)
        label.font = UIFont.systemFont(ofSize: 14)
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    lazy var textContent: UILabel = {
        let label = UILabel()
        label.numberOfLines = 2
        label.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
        label.font = UIFont.systemFont(ofSize: 14)
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    lazy var textTime: UILabel = {
        let label = UILabel()
        label.textColor = #colorLiteral(red: 0.6077751517, green: 0.6078823209, blue: 0.6077683568, alpha: 1)
        label.font = UIFont.systemFont(ofSize: 14)
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    lazy var button: UIButton = {
        let btn = UIButton(type: .system)
        btn.setTitle("查看详情", for: .normal)
        btn.translatesAutoresizingMaskIntoConstraints = false
        btn.addTarget(self, action: #selector(handleBtn), for: .touchUpInside)
        return btn
    }()
    
    lazy var downloadLayer: CAShapeLayer = {
        let centerX:CGFloat = UIScreen.main.bounds.width / 2
        let path = UIBezierPath(arcCenter: CGPoint(x: centerX, y: center.y), radius: 30, startAngle: -CGFloat.pi / 2, endAngle: CGFloat.pi * 1.5, clockwise: true)
        let layer = CAShapeLayer()
        layer.path = path.cgPath
        layer.fillColor = UIColor.clear.cgColor
        layer.strokeColor = #colorLiteral(red: 0.1764705926, green: 0.4980392158, blue: 0.7568627596, alpha: 1).cgColor
        layer.lineWidth = 3
        layer.lineCap = .round
        layer.strokeEnd = 0
        return layer
    }()
    
    @objc fileprivate func handleBtn() {
        delegate?.btnClick(index: currentIndex)
    }
}

//MARK: - <UIScrollViewDelegate>

extension MKImageViewCell: UIScrollViewDelegate {
    func viewForZooming(in scrollView: UIScrollView) -> UIView? {
        return browseImageView
    }
    
    func scrollViewDidZoom(_ scrollView: UIScrollView) {
        let x = scrollView.bounds.width > scrollView.contentSize.width ? (scrollView.bounds.width - scrollView.contentSize.width) / 2 : 0
        let y = scrollView.bounds.height > scrollView.contentSize.height ? (scrollView.bounds.height - scrollView.contentSize.height) / 2 : 0
        browseImageView.center = CGPoint(x: scrollView.contentSize.width / 2 + x, y: scrollView.contentSize.height / 2 + y)
    }
    
    func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
        isZooming = true
    }
    
    func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) {
        isZooming = false
    }
}

//MARK: - <UIGestureRecognizerDelegate>

extension MKImageViewCell: UIGestureRecognizerDelegate {
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

//MARK: - Handle Tap/Pan Gesture

extension MKImageViewCell {
    
    @objc func handleDoubleGesture(gesture: UITapGestureRecognizer) {
        
        if initFrame != nil {
            if scrollView.zoomScale == 1 {
                // 放大点击的区域（减去误差）
                let location = gesture.location(in: scrollView)
                scrollView.zoom(to: CGRect(x: location.x - initFrame!.origin.x, y: location.y - initFrame!.origin.y, width: 10, height: 10), animated: true)
            } else {
                // 缩小
                scrollView.zoom(to: scrollView.frame, animated: true)
            }
        }
    }
    
    @objc func handleTapGesture() {
        if startInteract == false && shouldStart == false {
            delegate?.cellDidTap()
        }
    }
    
    // 浏览长图时，如果放大了长图 返回true；反之返回false。
    fileprivate func longPictureIsZoom() -> Bool {
        return scrollView.zoomScale != 1 && browseImageView.frame.height > UIScreen.main.bounds.height
    }
    
    @objc func handlePanGesture(gesture: UIPanGestureRecognizer) {
        if isZooming == true {
            return
        }
        if longPictureIsZoom() {
            return
        }
        let point = gesture.location(in: self)
        let percent = abs(point.y - startPoint.y) / UIScreen.main.bounds.height * 2
        
        if gesture.state == .began {
            // 开始
            startPoint = point
            startInteract = false
            shouldStart = false
        } else if gesture.state == .ended || gesture.state == .cancelled || gesture.state == .failed || gesture.state == .recognized {
            // 结束
            if shouldStart && startInteract {
                if percent > 0.3 {
                    let y = point.y - startPoint.y > 0 ? UIScreen.main.bounds.height / 2 : -UIScreen.main.bounds.height / 2
                    
                    UIView.animate(withDuration: 0.25, animations: {
                        self.alpha = 0
                        self.browseImageView.transform = CGAffineTransform(translationX: 0, y: y)
                    }) { (_) in
                        self.delegate?.dismissNow()
                    }
                } else {
                    // 取消
                    delegate?.shouldScroll(bool: true)
                    UIView.animate(withDuration: 0.25, animations: {
                        self.alpha = 1.0
                        self.browseImageView.transform = .identity
                    }) { (_) in
                        self.delegate?.fillBg()
                        self.textView.alpha = 1
                        self.startInteract = false
                        self.shouldStart = false
                    }
                }
            }
        } else if gesture.state == .changed {
            // 移动
            if startInteract == false {
                let offsetX = abs(point.x - startPoint.x)
                let offsetY = abs(point.y - startPoint.y)
                if offsetX + offsetY > 5 {
                    if scrollView.contentSize.height > UIScreen.main.bounds.height {
                        if scrollView.contentOffset.y <= 0 {
                            startInteract = true
                            shouldStart = offsetY > offsetX + 3
                        }
                    } else {
                        startInteract = true
                        shouldStart = offsetY > offsetX + 3
                    }
                }
            }
            if shouldStart == true && startInteract == true {
                if self.frame.origin.x != CGFloat(currentIndex) * self.frame.width {
                    shouldStart = false
                } else {
                    textView.alpha = 0
                    scrollView.zoomScale = 1
                    // 开始交互动画
                    delegate?.clearBg()
                    delegate?.shouldScroll(bool: false)
                    browseImageView.transform = CGAffineTransform(translationX: 0, y: point.y - startPoint.y)
                    alpha = (1.0 - percent) * 2
                }
            }
        }
    }
}

//MARK: - UI

extension MKImageViewCell {
    fileprivate func setUI() {
        backgroundColor = UIColor.black
        contentView.addSubview(scrollView)
        scrollView.addSubview(browseImageView)
    }
}
